﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RRRSRoguelike;
using System.Drawing;
using RRRSRoguelike.Entities;
using RRRSRoguelike.Screens;
using RRRSRoguelike.Helpers;

namespace RRRSRoguelike.Managers
{
     
    class DungeonManager
    {

        #region variables
        public Random DungeonBuilderRandom;
        public Random GeneralRandom;
        private int seed;
        
        public Dungeon Dungeon;
        private Player player;
        

        //Managers
        public CreatureManager CreatureManager;
        public PropManager PropManager;
        public DungeonVisualizer DungeonVisualizer;
                
        //Flags
        private int currentDungeonLevel = 1;
        public bool gameOver = false;
        public bool Redraw = false;

        //Screens
        QuitScreen quitScreen;

        #endregion

        #region singleton
        //This pattern allows the manager to be initialized and used as a static.  Lovely.
        static readonly DungeonManager instance = new DungeonManager();

        public static DungeonManager Instance
        {
            get { return instance; }
        }
        #endregion

        #region properties
        
        /// <summary>
        /// Holds the currentlevel.  Very important
        /// </summary>
        public int CurrentDungeonLevel
        {
            get { return currentDungeonLevel; }
            set { currentDungeonLevel = value;}
        }

        public int Seed{get {return seed;}}
        

        public DungeonLevel DungeonLevel
        {
            get { return Dungeon.Levels[currentDungeonLevel-1]; }
            set { Dungeon.Levels[currentDungeonLevel-1] = value; }
        }

        public bool? PlayerHasWon
        {
            get { return CreatureManager.PlayerAlive && !IsGameActive; }
        }

        //read only flag
        public bool IsGameActive
        {
            get { return (player.Hits > 0 && !gameOver); }
        }

        #endregion

        #region methods


        /// <summary>
        /// Initialize all the managers and set the flags
        /// </summary>
        /// 
        public void Initialize(int seed = -1) 
        {
            if (quitScreen == null)
                quitScreen = new QuitScreen();

            SetSeed(seed);

            currentDungeonLevel = 1;
            gameOver = false;
                        
            Dungeon = new Dungeon();
            Dungeon.Levels.Add(new DungeonLevel(currentDungeonLevel, Constants.DungeonWidth, Constants.DungeonHeight));
            InitializeManagers();
            //Does this dungeon building code belong here?          
            DungeonLevel.CreateRandomDungeonObjects();

            player = CreatureManager.Player;
        }

        private void SetSeed(int seed = -1)
        {
            GeneralRandom = new Random();
            //create a seed            
            if (seed != -1)
                this.seed = seed;
            else
                this.seed = CreateSeed(5);

            //This is why the swords were in the same place, using seed instead of this.seed.
            DungeonBuilderRandom = new Random(this.seed);
        }
        /// <summary>
        /// Does what is says on the tin.
        /// </summary>
        private void InitializeManagers()
        {
            //If you code a new manager don't forget to add it here.
            CreatureManager = new CreatureManager();
            PropManager = new PropManager();
            DungeonVisualizer = new DungeonVisualizer();

            
        }


        //This visual stuff doesn't belong here.

        /// <summary>
        /// This is used to give the user a visual cue if something has changed but won't be updated in time/at all.
        /// </summary>
        public void ForceRedraw()
        {
            Redraw = true;
            DrawDungeon();
        }

        /// <summary>
        /// Prepares tiles and calls the visualizer
        /// </summary>
        public void DrawDungeon()
        {
            if (Redraw)
            {
                SetAllDungeonObjectsToTiles();
                DungeonVisualizer.Visualize(DungeonLevel,false);
                //this is used to reduce the number of redraws, reducing flicker.
                Redraw = false;
            }
        }

        /// <summary>
        /// This currently calls the separate manager to turn their entities into tiles for drawing.
        /// </summary>
        private void SetAllDungeonObjectsToTiles()
        {
            DungeonLevel.Clear();
            PropManager.PropsToTiles();
            CreatureManager.CreaturesToTiles();
            // Perhaps walls shoud be props?  Would allow for different rooms.
            DungeonLevel.walls.ToList().ForEach(w => DungeonLevel.AddTile(w));   
        }

        /// <summary>
        /// Makes the Soundmanager call cleaner in other classes.
        /// </summary>
        /// <param name="sound"></param>
        public void PlaySound(SoundList sound)
        {
            GameManager.Instance.SoundManager.PlaySound(sound.ToString());
        }

        private int CreateSeed(int length) 
        {
            StringBuilder seedstring = new StringBuilder(GeneralRandom.Next(1, 9).ToString());
            for (int i = 0;i<length-1;i++)
            {
                seedstring.Append(GeneralRandom.Next(0,9).ToString());
            }

            return int.Parse(seedstring.ToString());
        
        }

        #endregion

    }
}
